import json

from django.shortcuts import render
from django.views import View
from django import http
from meiduocxn.libs.captcha.captcha import captcha
from django_redis import get_redis_connection
import random
from celery_tasks.sms.tasks import send_sms_code
from meiduocxn.utils.response_code import RET, RETCODE
from users.models import User
from verifications import constants


# Create your views here.
class ImageCodeView(View):
    def get(self,request,image_code_id):
        # 1,生成图片验证码
        name,text,image_data = captcha.generate_captcha()
        print(text)
        # 2,保存图片验证码到redis中
        redis_conn = get_redis_connection("code")
        # 参数1: 保存到redis键,  参数2: 有效期,  参数3: 值
        redis_conn.setex("img_code_%s"%image_code_id,300,text)

        # 3,返回图片验证码
        return http.HttpResponse(image_data,content_type="image/png")


class SmsCodeView(View):
    def get(self,request,mobile):
        # 1,获取参数
        image_code = request.GET.get("image_code")
        image_code_id = request.GET.get("image_code_id")

        # 2,校验参数
        # 2,1 为空校验
        if not all([image_code,image_code_id]):
            return http.JsonResponse({"code":RET.PARAMERR,"errmsg":"参数不完整"})

        # 2,2 获取redis中的图片验证码,校验为空
        redis_conn = get_redis_connection("code")
        pipeline = redis_conn.pipeline()  # 开启管道(事务)
        redis_image_code = redis_conn.get("img_code_%s"%image_code_id)

        # 判断是否过期
        if not redis_image_code:
            return http.JsonResponse({"code": RET.NODATA, "errmsg": "图片验证码过期"})

        # 删除redis验证码
        redis_conn.delete("img_code_%s"%image_code_id)

        # 2,3 图片验证码正确性
        if image_code.lower() != redis_image_code.decode().lower():
            return http.JsonResponse({"code": RET.DATAERR, "errmsg": "图片验证码错误"})
        # 获取短信验证码标记
        send_flag = redis_conn.get("send_flag_%s" % mobile)
        if send_flag:
            return http.JsonResponse({"code": RET.DATAERR, "errmsg": "短信发送频繁"}, status=400)

        # 3,发送短信,并判断是否发送成功
        sms_code = "%06d"%random.randint(0,999999)
        print("sms_code = %s"%sms_code)
        # ccp = CCP()
        # result = ccp.send_template_sms(mobile, [sms_code, constants.REDIS_SMS_CODE_EXPIRES/60], 1)
        #
        #  #判断是否发送成功
        # if result == -1:
        #     return http.JsonResponse({"code": RET.THIRDERR, "errmsg": "短信发送失败"})

        from celery_tasks.sms.tasks import send_sms_code
        send_sms_code.delay(mobile, sms_code, constants.REDIS_SMS_CODE_EXPIRES / 60)

        # 保存短信验证到redis
        redis_conn.setex("sms_code_%s"%mobile,constants.REDIS_SMS_CODE_EXPIRES,sms_code)
        redis_conn.setex("send_flag_%s" % mobile, 60, "True")

        pipeline.setex("sms_code_%s" % mobile, constants.REDIS_SMS_CODE_EXPIRES, sms_code)
        pipeline.setex("send_flag_%s" % mobile, 60, 'True')
        pipeline.execute()  # 提交管道(事务)
        # 4,返回响应
        return http.JsonResponse({"code":RET.OK,"errmsg":"ok"})


class PwdCodeView(View):
    def get(self,request,username):
        # 接收
        uuid = request.GET.get('image_code_id')
        image_code = request.GET.get('text')
        # 2.图形验证码是否正确
        # 2.1从redis中读取之前保存的图形验证码文本
        redis_cli_image = get_redis_connection('code')
        image_code_redis = redis_cli_image.get("img_code_%s"%uuid)
        # 2.2如果redis中的数据过期则提示
        if image_code_redis is None:
            return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码已过期，点击图片换一个'})
        # 2.3立即删除redis中图形验证码，表示这个值不能使用第二次
        redis_cli_image.delete(uuid)
        # 2.3对比图形验证码：不区分大小写
        if image_code_redis.decode().lower() != image_code.lower():
            return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码错误'})
        try:
            user = User.objects.get(username=username)
        except:
            return http.JsonResponse({}, status=404)
        # 处理
        # json_str = json.dumps({"user_id": user.id, 'mobile': user.mobile})
        # print(json_str)
        from itsdangerous.jws import TimedJSONWebSignatureSerializer as TJWSSerializer
        from django.conf import settings
        serializer = TJWSSerializer(secret_key=settings.SECRET_KEY, expires_in=300)
        json_dict = {"user_id": user.id, 'mobile': user.mobile}
        # 2,加密数据
        json_str = serializer.dumps({"access_token": json_dict})
        json_str = json_str.decode()
        print(json_str)
        return http.JsonResponse({'mobile': user.mobile, 'access_token': json_str})


class PwdSMSCodeView(View):
    def get(self,request):
        access_token = request.GET.get('access_token')
        from itsdangerous.jws import TimedJSONWebSignatureSerializer as TJWSSerializer
        from django.conf import settings
        serializer = TJWSSerializer(secret_key=settings.SECRET_KEY, expires_in=300)
        # 2,解密数据
        json_dict = serializer.loads(access_token)
        mobile = json_dict['access_token']['mobile']
        try:
            User.objects.get(mobile=mobile)
        except:
            return http.JsonResponse({}, status=400)
            # 验证
        redis_cli_sms = get_redis_connection('code')
        # 0.是否60秒内
        if redis_cli_sms.get(mobile + '_flag') is not None:
            return http.JsonResponse({'code': RETCODE.SMSCODERR, 'errmsg': '发送短信太频繁，请稍候再发'})
        # # 处理
        # # 1.生成随机6位数
        sms_code = '%06d' % random.randint(0, 999999)
        print(sms_code)
        # 优化：使用管道
        redis_pl = redis_cli_sms.pipeline()
        redis_pl.setex("sms_code_%s" % mobile, constants.REDIS_IMAGE_CODE_EXPIRES, sms_code)
        redis_pl.setex(mobile + '_flag', constants.SMS_CODE_FLAG, 1)
        redis_pl.execute()
        # 3.发短信
        # 通过delay调用，可以将任务加到队列中，交给celery去执行
        send_sms_code.delay(mobile, sms_code,300)
        # 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})


class PwdCheckCodeView(View):
    def get(self,request,username):
        sms_code = request.GET.get('sms_code')
        try:
            user = User.objects.get(username=username)
        except:
            return http.JsonResponse({}, status=400)
        redis_cli = get_redis_connection('code')
        sms_code_redis = redis_cli.get("sms_code_%s" % user.mobile)
        # 2.判断是否过期
        if sms_code_redis is None:
            return http.HttpResponseForbidden('短信验证码已经过期')
        # 3.删除短信验证码，不可以使用第二次
        redis_cli.delete("sms_code_%s" % user.mobile)
        redis_cli.delete(user.mobile + '_flag')
        # 4.判断是否正确
        if sms_code_redis.decode() != sms_code:
            return http.HttpResponseForbidden('短信验证码错误')
        from itsdangerous.jws import TimedJSONWebSignatureSerializer as TJWSSerializer
        from django.conf import settings
        serializer = TJWSSerializer(secret_key=settings.SECRET_KEY, expires_in=300)
        json_dict = {"user_id": user.id, 'mobile': user.mobile}
        # 2,加密数据
        json_str = serializer.dumps({"access_token": json_dict})
        json_str = json_str.decode()
        return http.JsonResponse({'user_id': user.id, 'access_token': json_str})